﻿using LeafTransmission.Entity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;

namespace LeafTransmission.Utils
{
    /*
     * 用于传输文件相关的TCP工具类
     * BytesToT 与 TToBytes请勿使用
     * 使用 Serialize进行序列化 Deserialize进行反序列化, 对应得实体类应添加 [Serialize]
     * 注意 BinaryFormatter 存在安全问题,尽量不使用 由于本应用为本地作业,故不考虑
     * https://learn.microsoft.com/zh-cn/dotnet/standard/serialization/binaryformatter-security-guide
     */
    internal class GeneralTool
    {
        // 合并两个byte数组
        public static byte[] MergeBytes(byte[] arg1, byte[] arg2)
        {
            byte[] container = new byte[arg1.Length + arg2.Length];
            arg1.CopyTo(container, 0);
            arg2.CopyTo(container, arg1.Length);
            return container;
        }

        

        public static byte[] Serialize<T>(T t)
        {
            byte[] arr = null;
            if (t != null)
            {
                using (MemoryStream mStream = new MemoryStream())
                {
                    BinaryFormatter formatter = new BinaryFormatter();
                    formatter.Serialize(mStream, t);
                    mStream.Flush();
                    arr = mStream.ToArray();
                }
            }
            return arr;
        }
        public static T Deserialize<T>(byte[] arr)
        {
            T t = default;
            using (MemoryStream mStream = new MemoryStream())
            {
                mStream.Write(arr, 0, arr.Length);
                mStream.Flush();
                mStream.Position = 0;
                BinaryFormatter formatter = new BinaryFormatter();
                t = (T)formatter.Deserialize(mStream);
            }
            return t;
        }


        // 字节转对象
        public static T BytesToT<T>(byte[] arr)
        {
            T temp = default(T);
            int size = Marshal.SizeOf(temp);
            IntPtr ptr = Marshal.AllocHGlobal(size); //声明一块非托管内存，用于存放arr
            Marshal.Copy(arr, 0, ptr, size);//将arr存入声明的内存里
            try
            {
                temp = (T)Marshal.PtrToStructure(ptr, temp.GetType());// 将这一块内存转为T类型
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            finally
            {
                Marshal.FreeHGlobal(ptr);//释放刚才声明的非托管内存
            }
            
            return temp;
        }

        // 对象转字节
        public static byte[] TToBytes<T>(T t)
        {
            int size = Marshal.SizeOf(t);
            byte[] arr = new byte[size];
            IntPtr ptr = Marshal.AllocHGlobal(size);
            Marshal.StructureToPtr(t, ptr, true);
            Marshal.Copy(ptr, arr, 0, size);
            Marshal.FreeHGlobal(ptr);
            return arr;
        }
    }
}
